<?php
namespace app\api\module;

use app\common\model\TokenException;
use \think\Model;
use  \think\Db;

use app\common\model\UserException;
use app\common\model\DeveloperException;
use app\common\model\ServerException;
use app\common\model\User;

/**
 *
 * @apiDefine tnCommonParamTN
 *
 * @apiHeader (公共参数) {String} version 接口版本.
 * @apiHeader (公共参数) {String} module 接口模块ID.
 * @apiHeader (公共参数) {String} interface 接口ID.
 * @apiHeader (公共参数) {Object} data 接口请求数据
 *
 */

/**
 * @apiDefine dataGroup data-请求数据
 */

/**
 * @apiDefine dkqCommonResponse
 *
 * @apiSuccess (基础报文信息) {String} result_code 结果编码.
 * @apiSuccess (基础报文信息) {String} result_info  结果信息.
 * @apiSuccess (基础报文信息) {Object} result_data  回执报文数据.
 */

/**
 * @apiDefine baseResponse 基础报文信息
 */

/**
 * @apiDefine dataResponse result_data-回执报文信息
 */

class Common extends Model
{
    public function __construct($data = "")
    {
        parent::__construct($data);

        //模块名
        $module = substr(get_class($this), strripos(get_class($this), "\\") + 1);

        //加载常量定义
        $constFile = __DIR__ . "/../def/" . $module . ".def.php";
        if (file_exists($constFile))
        {
            require_once $constFile;
        }

        $this->response = array();
    }

    /**
     * @param $interface
     * @param $data
     */
    public function execModule($interface, $data)
    {
        //存储请求报文
        $this->request = $data;

        Db::startTrans();
        try
        {
            //判断是否需要登录
            if ($this->needLogin($interface))
            {
                if (!array_key_exists("access_token", $this->request) || $this->request["access_token"] == "")
                {
                    throw new TokenException("请先进行登录操作！");
                }
            }

            //执行接口
            $result = $this->exec($interface);

            Db::commit();

            //返回结果
            return $result;
        }
        catch (ServerException $exception)
        {
            Db::rollback();

            //发送服务器级别错误
            send_server_error($exception->getMessage());
        }
        catch (DeveloperException $exception)
        {
            Db::rollback();

            //发送开发者级错误
            send_developer_error($exception->getMessage());
        }
        catch (UserException $exception)
        {
            Db::rollback();

            //发送用户级别错误
            send_user_error($exception->getMessage());
        }
        catch (TokenException $exception)
        {
            Db::rollback();

            //发送登录异常错误
            send_token_error($exception->getMessage());
        }
        catch (\Exception $exception)
        {
            Db::rollback();

            //发送服务器级别错误
            send_server_error($exception->getMessage() . $exception->getFile() . $exception->getLine());
        }
    }

    protected function exec($interface)
    {

    }

    /**
     * 获取必选字段
     *
     * @param $param
     * @return mixed
     * @throws DeveloperException
     */
    protected function essentialParam($param)
    {
        if (array_key_exists($param, $this->request))
        {
            if ($this->request[$param] === "")
            {
                send_developer_error("必选字段【" . $param . "】不能为空！");
            }
            return $this->request[$param];
        }
        else
        {
            throw new DeveloperException("必选字段【" . $param . "】不存在,请核实文档后重试！");
        }
    }

    /**
     * 获取可选参数
     *
     * @param $param
     * @return string
     */
    protected function optionalParam($param)
    {
        if (array_key_exists($param, $this->request))
        {
            return $this->request[$param];
        }
        else
        {
            return "";
        }
    }

    /**
     * 是否需要用户登录,默认所有操作均需用户登录
     *
     * @param $interface
     * @return bool
     */
    protected function needLogin($interface)
    {
        return true;
    }

    //插入结果报文
    protected function insertResponse($key, $value)
    {
        //将报文进行字符串编码(将null或数值转为字符串)
        $this->encodeResponse($value);

        if ($key)
        {
            $this->response["result_data"][$key] = $value;
        }
        else
        {
            $this->response["result_data"] = $value;
        }
    }

    //输出响应报文
    protected function response($info = "")
    {
        //添加结果编码
        $this->response["result_code"] = "0000";
        //添加结果信息
        $this->response["result_info"] = $info;

        return $this->response;
    }

    /**
     * 获取当前用户
     *
     * @param bool $must
     * @return array|null
     * @throws TokenException
     */
    protected function currentUser($must = true)
    {
        if ($must)
        {
            if (!array_key_exists("access_token", $this->request) || $this->request["access_token"] == "")
            {
                throw new TokenException("请先进行登录操作！");
            }
            //获取token值
            $token = $this->request["access_token"];

            return User::userFromToken($token);
        }
        else
        {
            //获取token值
            $token = $this->optionalParam("access_token");

            return empty($token) ? null : User::userFromToken($token);
        }
    }


    /**
     * 对报文进行编码
     *
     * @param $response                 报文内容
     */
    private function encodeResponse(&$response)
    {
        //如果是数组,遍历元素进行编码
        if (is_array($response))
        {
            foreach ($response as &$item)
            {
                $this->encodeResponse($item);
            }
        }
        //如果不是数组,将报文内容转为字符串
        else
        {
            if ($response === false)
            {
                $response = "0";
            }
            elseif (is_null($response))
            {
                $response = "";
            }
            else
            {
                $response = strval($response);
            }
            return;
        }
    }

    //请求报文
    protected $request;
    //回执报文
    private $response;
}